#!/usr/bin/python
# -- coding:utf8 --
import asyncio
import os
from pathlib import Path
import pickle
import platform
import sys

# import app
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import roc_auc_score
# from bayes_opt import BayesianOptimization
import warnings
import pandas as pd
import numpy as np
import re
from sklearn.metrics import roc_curve, auc
# import matplotlib.pyplot as plt
from lightgbm.sklearn import LGBMRegressor
from lightgbm.sklearn import LGBMClassifier
# from sklearn.grid_search import GridSearchCV
import datetime
import os
from sklearn.model_selection import KFold
from collections import Counter
import unidecode
from hyperopt import fmin, tpe, hp
import requests,json,time,random

import logging

# 配置日志记录器
logging.basicConfig(filename='module_timing.log',  # 日志文件名
                    level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S')  # 时间格式


# 忽略警告
# warnings.filterwarnings('ignore')

if platform.system() != "Windows":
    import uvloop
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
else:
    import nest_asyncio
    nest_asyncio.apply()

pd.options.display.max_rows=1000
pd.options.display.max_columns=1000
pd.options.display.width=1000


def cal_strdate_to_int(apply_time):
    s_t  = time.strptime(apply_time, "%Y-%m-%d %H:%M:%S")
    return int(time.mktime(s_t))*1000

def cal_strdate_to_datetime(apply_time):
    s_t = time.strptime(str(apply_time), "%Y-%m-%d %H:%M:%S")
    s_t = int(time.mktime(s_t)) * 1000
    date_time = datetime.datetime.fromtimestamp(s_t / 1000)
    return date_time

def tmp_d(fz,fm):
    if  fm==0 or not fm  :
        return -999
    else:
        return round(fz / fm, 4)


# file_path_name = './model/ph_reg_20240715.json'
# current_path = os.path.dirname(__file__)
# file_path_name = file_path_name.replace("./", current_path + "/")
# with open(file_path_name, 'r') as f:
#     ph_reg = json.load(f)

# package_id_2m = ph_reg["package_id_2m"]
# package_id_1m = ph_reg["package_id_1m"]
# package_id_50w = ph_reg["package_id_50w"]
# package_id_loan = ph_reg["package_id_loan"]
# package_id_48 = ph_reg["package_id_48"]
# package_id_46 = ph_reg["package_id_46"]
# package_id_44 = ph_reg["package_id_44"]
# package_id_42 = ph_reg["package_id_42"]
# sms_org_pattern = ph_reg["sms_org_pattern"]
# sms_topcash_key = ph_reg["sms_topcash_key"]
# sms_1m_cash_key = ph_reg["sms_1m_cash_key"]
# sms_dele_key = ph_reg["sms_dele_key"]
# sms_cash_key = ph_reg["sms_cash_key"]
# sms_loan_key = ph_reg["sms_loan_key"]
# sms_repayment_key = ph_reg["sms_repayment_key"]
# sms_expire_key = ph_reg["sms_expire_key"]
# sms_overdue_key = ph_reg["sms_overdue_key"]
# sms_overdue_serious_key = ph_reg["sms_overdue_serious_key"]
# sms_verif_key = ph_reg["sms_verif_key"]
# sms_bill_key = ph_reg["sms_bill_key"]
# app_del_key = ph_reg["app_del_key"]


def get_ph_reg(request = None):

    if request:
        ph_reg = request.app.state.jsons.get('ph_reg_20240715.json', None)
        # print(ph_reg)
    else:
        ph_reg = None
        
    if ph_reg is not None:
        # 使用 ph_reg_data
        # print(ph_reg)
        pass
    else:
        file_path_name = './model/ph_reg_20240715.json'
        current_path = os.path.dirname(__file__)
        file_path_name = file_path_name.replace("./", current_path + "/")
        with open(file_path_name, 'r') as f:
            ph_reg = json.load(f)
    
    return ph_reg

def get_pickle(file_name, request = None):
    if request:
        pkl = request.app.state.models.get(file_name, None)
    else:
        pkl = None
    
    if pkl is not None:
        pass
    else:
        file_path_name = './model/'+file_name
        current_path = os.path.dirname(__file__)
        file_path_name = file_path_name.replace("./", current_path + "/")
        file_path_name = file_path_name.replace("\\\\", "/")
        with open(file_path_name, 'rb') as f:
            pkl = pickle.load(f)
    
    return pkl

# 计算逾期天数 如果数据库计算不出来用当前时间计算
def cal_overdue_days_xw(info):
    should_date = info["ReDate"]
    pay_date = info["CompleteDate"]
    should_date = str(should_date)[:10]
    late_day = -999
    if pay_date == "NaT" or  pay_date == None:
        should_date = datetime.datetime.strptime(should_date, '%Y-%m-%d')
        now = datetime.datetime.strptime(str(datetime.datetime.now())[:10], '%Y-%m-%d')
        late_day = (now - should_date).days
    if pay_date != "NaT" and pay_date != None :
        pay_date = str(pay_date)[:10]
        pay_date = datetime.datetime.strptime(pay_date, '%Y-%m-%d')
        should_date = datetime.datetime.strptime(should_date, '%Y-%m-%d')
        late_day = (pay_date - should_date).days
    return late_day



def cal_sms_content(x):
    x = str(x)
    x = x.lower()
    x = re.sub(r'[^a-zA-Z0-9 %]', '', x)
    x = re.sub("lon", "loan", x)
    x = re.sub("ioan", "loan", x)
    x = re.sub("lon", "loan", x)
    x = re.sub("csh", "cash", x)
    x = re.sub("u0005", "", x)
    x = re.sub("u001b", "", x)
    x = re.sub("cah", "cash", x)
    x = re.sub("pes0", "peso", x)
    x = re.sub(" ccount", " account", x)  # ovedue
    x = re.sub("ovedue", "overdue", x)  # collectio
    x = re.sub(" collectio ", " collection ", x)  # collectio

    # 正则更简单
    x = re.sub("days", " day", x)

    x = re.sub(' {2,}', ' ', x)  # 空格>=2 替换成1个
    x = x.lstrip()
    return x

def cal_tq_org_02(x):
    x = str(x).lower()
    x = re.sub(r'[^a-zA-Z0-9áéíóúüÁÉÍÓÚÜ@]', '', x)
    sms_org_pattern = get_ph_reg()["sms_org_pattern"]
    pattern = sms_org_pattern
    matches = re.search(pattern, x)
    #matches = re.match(pattern, x)
    y="-999"
    if matches:
        s = matches.start()
        e = matches.end()
        y = x[s:e]
    if len(y)>=16:
        y="-999"
    return y

def cal_tq_org(x):
    x = str(x)
    x = x.strip()
    x = unidecode.unidecode(x.lower())
    pattern = "$(.*?)$|<(.*?)>|【(.*?)】|\[(.*?)\]|\((.*?)\)|\{(.*?)\}|（(.*?)）|(^[^0-9]{0,15}):|(^[^0-9]{0,15})："
    matches = re.search(pattern, x)
    #matches = re.match(pattern, x)
    y="-999"
    if matches:
        s = matches.start()
        e = matches.end()
        y = x[s:e]
        y = re.sub(r'[^a-zA-Z0-9áéíóúüÁÉÍÓÚÜ]', '', y)  # 保留数字英文和空格
        y = re.sub("ioan", "loan", y)
        y = re.sub("lon", "loan", y)
        y = re.sub("csh", "cash", y)
        y = re.sub("u0005", "", y)
        y = re.sub("u001b", "", y)
        y = re.sub("cah", "cash", y)

        y = y.strip()


    if len(y)>=16:
        y="-999"
    return y


def cal_boy_type(x, type):
    y = 0
    if re.search(type, x):
        y = 1
    return y

def subtract_days_from_date_str(date_str, days):
    date_format = "%Y-%m-%d %H:%M:%S"
    date_obj = datetime.datetime.strptime(date_str, date_format)
    new_date_obj = date_obj - datetime.timedelta(days=days)
    new_date_str = new_date_obj.strftime(date_format)
    return new_date_str


def cal_timestamp(install_timeStamp):  # 时间戳计算 返回 年月日
    create_time = datetime.datetime.fromtimestamp(float(install_timeStamp)/1000)
    return create_time

def cal_hours(a,b):
    tmp = a-b
    hours = tmp.days*24+tmp.seconds/3600
    return hours

def fix_file_path(file_path_name):
    # 如果是绝对路径,则直接返回
    if os.path.isabs(file_path_name):
        return file_path_name
    
    # current_path = os.path.dirname(__file__)
    # file_path_name = file_path_name.replace("./", current_path + "/")
    # file_path_name = file_path_name.replace("\\\\", "/")
    # return file_path_name
    
    # 处理相对路径
    current_path = Path(os.path.dirname(__file__))
    file_path = current_path / file_path_name.lstrip("/")
    return str(file_path.resolve())

def load_data_from_pickle(file_path_name):
    """
    加载pkl格式数据
    :param file_path_name:
    :return:
    """
    current_path = os.path.dirname(__file__)
    file_path_name = file_path_name.replace("./", current_path + "/")
    file_path_name = file_path_name.replace("\\\\", "/")
    with open(file_path_name, "rb") as infile:
        result = pickle.load(infile)
    return result


"""
案例，订单 = 170762701922469350
构造参数 params
"""



# params = {}
# params["order_id"]=order_id
# params["apply_time"]=ApplyDate
# params["birthday"]="1987-5-6"
# params["degree"]=1
# params['app_data']= app_json
# params['sms_json']= sms_json
# params['ProjectId']= 10070

# with open('params.json', 'w') as f:
#     json.dump(params, f)



# current_path = os.path.dirname(__file__)

# params_file_path_name = './model/params.json'
# # params_file_path_name = params_file_path_name.replace("./", current_path + "/")
# params_file_path_name = fix_file_path(params_file_path_name)
# with open(params_file_path_name, 'r') as f:
#     params = json.load(f)
# print("成功读取：params")

# old_params_file_path_name = './model/params_old.json'
# # old_params_file_path_name = old_params_file_path_name.replace("./", current_path + "/")
# old_params_file_path_name = fix_file_path(old_params_file_path_name)
# with open(old_params_file_path_name, 'r') as f:
#     params_old = json.load(f)
# print("成功读取：params_old")

# pickle_file_path_name = './model/old_v1_20240714.pkl'
# pickle_file_path_name = fix_file_path(pickle_file_path_name)
# print(pickle_file_path_name)
# with open(pickle_file_path_name, 'rb') as f:
#     v1_old_model = pickle.load(f)
    
def load_pickle(file_path_name):
    
    file_path_name = fix_file_path(file_path_name)
    
    # current_path = os.path.dirname(__file__)
    # file_path_name = file_path_name.replace("./", current_path + "/")
    # file_path_name = file_path_name.replace("\\\\", "/")
    
    pkl = pickle.load(open(file_path_name, 'rb'))
    return pkl


def p2score(p, pdo=40, base_score=700):
        """
        概率转换为分数的函数
        说明：概率p=坏的概率
        :param p:
        :param pdo:
        :param base_score:
        :return:
        """
        b = pdo / np.log(2)
        a = base_score + b * np.log(1 / 20)
        if p < 0:
            return -99999
        min_p = 1e-9
        max_p = 1 - min_p
        if p >= max_p:
            p = max_p
        elif p <= min_p:
            p = min_p
        score = int(a + b * np.log((1 - p) / (p)))
        if score < 300:
            return 300
        elif score > 900:
            return 900
        else:
            return score


def get_old_v1_score(params, request = None):
    start_time = time.time()
    order_id = params["order_id"]
    apply_time = params["apply_time"]
    birthday = params["birthday"]
    degree = params["degree"]
    app_data = params["app_data"]
    sms_json = params["sms_json"]
    ProjectId = params['ProjectId']
    ApplyDate = str(params['apply_time'])
    created_at = str(params['apply_time'])

    # 手机号码
    id_number = params['id_number']
    # 老客数据
    id_number_json = params['id_number_json']
    # 判断是否是字符串
    if isinstance(id_number_json, str):
        id_number_json = json.loads(id_number_json)
    # pandas dataframe
    df_apply_all = pd.DataFrame(id_number_json)
    # 稍微清洗几个数据
    df_apply_all["id_number"] = id_number
    df_apply_all['fact_time'] = df_apply_all['CompleteDate'].map(lambda x: str(x))
    df_apply_all['fact_day'] = df_apply_all['CompleteDate'].map(lambda x: str(x)[:10])
    df_apply_all['apply_time_tmp_day'] = df_apply_all['ApplyDate'].map(lambda x: str(x)[:10])
    df_apply_all["created_at"] = df_apply_all["ApplyDate"].map(lambda x: str(x))
    df_apply_all["order_id"] = df_apply_all["ApplyNO"].map(lambda x: int(x))
    df_apply_all["loan_time"] = df_apply_all["CreateDate"].map(lambda x: str(x))
    df_apply_all["plan_repayment_amount"] = df_apply_all["Amount"]
    df_apply_all['overdue_days_xw'] = df_apply_all.apply(cal_overdue_days_xw, axis=1)
    # df_apply_all["ReDate"] = df_apply_all["ReDate"].map(lambda x: str(x))

    apply_time_tmp = ApplyDate
    # apply_time = datetime.datetime.strptime(ApplyDate, '%Y-%m-%d %H:%M:%S').timestamp()  # 时间戳
    # df_apply_all.to_json('df_apply_all.json', orient='records')

    apply_time = str(apply_time)
    apply_time_int = cal_strdate_to_int(str(apply_time))
    apply_time_datetime = cal_strdate_to_datetime(apply_time)

    y=str(birthday)[:4]
    x = str(apply_time)[:4]
    age = int(x)-int(y)


    """ 本地json """
    ph_reg = get_ph_reg(request)
    package_id_2m = ph_reg["package_id_2m"]
    package_id_1m = ph_reg["package_id_1m"]
    package_id_50w = ph_reg["package_id_50w"]
    package_id_loan = ph_reg["package_id_loan"]
    package_id_48 = ph_reg["package_id_48"]
    package_id_46 = ph_reg["package_id_46"]
    package_id_44 = ph_reg["package_id_44"]
    package_id_42 = ph_reg["package_id_42"]
    sms_org_pattern = ph_reg["sms_org_pattern"]
    sms_topcash_key = ph_reg["sms_topcash_key"]
    sms_1m_cash_key = ph_reg["sms_1m_cash_key"]
    sms_dele_key = ph_reg["sms_dele_key"]
    sms_cash_key = ph_reg["sms_cash_key"]
    sms_loan_key = ph_reg["sms_loan_key"]
    sms_repayment_key = ph_reg["sms_repayment_key"]
    sms_expire_key = ph_reg["sms_expire_key"]
    sms_overdue_key = ph_reg["sms_overdue_key"]
    sms_overdue_serious_key = ph_reg["sms_overdue_serious_key"]
    sms_verif_key = ph_reg["sms_verif_key"]
    sms_bill_key = ph_reg["sms_bill_key"]
    app_del_key = ph_reg["app_del_key"]

    app_start_time = time.time()
    """ app """
    if isinstance(app_data, str):
        app_data = json.loads(app_data)
    app_data = [x for x in app_data if x['appName'] and x['packageName']
                and x['is_system'] == "0" and x['firstInstallTime'] >= "2020-01-01" and x[
                    'lastUpdateTime'] >= "2020-01-01"]

    n1 = len(app_data)
    app_data = [x for x in app_data if not (x['firstInstallTime'] == x['lastUpdateTime']
                                            and (apply_time_int - cal_strdate_to_int(
                x['firstInstallTime'])) / 3600 / 1000 / 24 / 365 >= 1)]
    n2 = len(app_data)
    app_data = [x for x in app_data if
                not re.search(app_del_key.lower(), x['appName'].lower() + x['packageName'].lower())]
    if len(app_data) <= 0:
        print("app缺失", order_id)


    app_id = [x['packageName'] for x in app_data]
    first_install_time = [cal_strdate_to_int(x['firstInstallTime']) for x in app_data]
    last_update_time = [cal_strdate_to_int(x['lastUpdateTime']) for x in app_data]

    in_hours = [(apply_time_int - x) / 3600 / 1000 / 24 + random.random() * 0.0001 for x in first_install_time]
    up_hours = [(apply_time_int - x) / 3600 / 1000 / 24 + random.random() * 0.0001 for x in last_update_time]
    all_hours = [(y - x) / 3600 / 1000 / 24 + random.random() * 0.0001 for x, y in
                 zip(first_install_time, last_update_time)]

    in_hours_int = [int(x) for x in in_hours]
    app_inday_majority = Counter(in_hours_int).most_common(1)[0][0]

    """ in """
    app_name_and_id = [x['appName'] + ' ' + x['packageName'] + "@ xw " + str(
        (apply_time_int - cal_strdate_to_int(x['firstInstallTime'])) / 3600 / 1000 / 24 + random.random() * 0.0001) for
                       x in app_data]
    app_1d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 1]
    app_3d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 3]
    app_7d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 7]
    app_15d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 15]
    app_30d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 30]
    app_60d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 60]
    app_90d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 90]
    app_180d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 180]
    app_360d = [app_name_and_id[in_hours.index(x)] for x in in_hours if x <= 360]

    app_name_and_id_gg = [x['packageName'] for x in app_data]
    app_1d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 1]
    app_3d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 3]
    app_7d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 7]
    app_15d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 15]
    app_30d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 30]
    app_60d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 60]
    app_90d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 90]
    app_180d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 180]
    app_360d_gg = [app_name_and_id_gg[in_hours.index(x)] for x in in_hours if x <= 360]

    app_3d_cnt_inday = len(app_3d)
    app_3d_cnt = len(app_3d)
    app_90d_cnt = len(app_90d)
    app_3d_div_90d_inday = tmp_d(app_3d_cnt, app_90d_cnt)

    app_cash_46_15d = [x for x in app_15d_gg if re.search(package_id_46, x + "@")]
    app_cash_46_15d_cnt = len(app_cash_46_15d)
    app_cash_46_360d = [x for x in app_360d_gg if re.search(package_id_46, x + "@")]
    app_cash_46_360d_cnt = len(app_cash_46_360d)
    app_cash_15d_div_360d_46_inday = tmp_d(app_cash_46_15d_cnt, app_cash_46_360d_cnt)

    app_cash_1d = [x for x in app_1d if re.search(package_id_loan, x)]
    app_cash_1d_cnt = len(app_cash_1d)
    app_1d_cnt = len(app_1d)
    app_cash_1d_rate_inday = tmp_d(app_cash_1d_cnt, app_1d_cnt)

    app_cash_3d = [x for x in app_3d if re.search(package_id_loan, x)]
    app_cash_3d_cnt = len(app_cash_3d)
    app_cash_180d = [x for x in app_180d if re.search(package_id_loan, x)]
    app_cash_180d_cnt = len(app_cash_180d)
    app_cash_3d_div_180d_inday = tmp_d(app_cash_3d_cnt, app_cash_180d_cnt)

    app_cash_3d = [x for x in app_3d if re.search(package_id_loan, x)]
    app_cash_3d_cnt = len(app_cash_3d)
    app_cash_30d = [x for x in app_30d if re.search(package_id_loan, x)]
    app_cash_30d_cnt = len(app_cash_30d)
    app_cash_3d_div_30d_inday = tmp_d(app_cash_3d_cnt, app_cash_30d_cnt)

    app_cash_48_7d = [x for x in app_7d_gg if re.search(package_id_48, x + "@")]
    app_cash_48_7d_cnt = len(app_cash_48_7d)
    app_cash_48_180d = [x for x in app_180d_gg if re.search(package_id_48, x + "@")]
    app_cash_48_180d_cnt = len(app_cash_48_180d)
    app_cash_7d_div_180d_48_inday = tmp_d(app_cash_48_7d_cnt, app_cash_48_180d_cnt)

    """ all """
    app_name_and_id = [x['appName'] + ' ' + x['packageName'] + "@ xw " + str(
        (cal_strdate_to_int(x['lastUpdateTime']) - cal_strdate_to_int(
            x['firstInstallTime'])) // 3600 / 1000 / 24 + random.random() * 0.0001) for x in
                       app_data]
    app_1d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 1]
    app_3d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 3]
    app_7d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 7]
    app_15d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 15]
    app_30d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 30]
    app_60d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 60]
    app_90d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 90]
    app_180d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 180]
    app_360d = [app_name_and_id[all_hours.index(x)] for x in all_hours if x <= 360]

    app_name_and_id_gg = [x['packageName'] for x in app_data]
    app_1d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 1]
    app_3d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 3]
    app_7d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 7]
    app_15d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 15]
    app_30d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 30]
    app_60d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 60]
    app_90d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 90]
    app_180d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 180]
    app_360d_gg = [app_name_and_id_gg[all_hours.index(x)] for x in all_hours if x <= 360]

    app_3d_cnt_allday = len(app_3d)
    app_3d_cnt = len(app_3d)
    app_30d_cnt = len(app_30d)
    app_3d_div_30d_allday = tmp_d(app_3d_cnt, app_30d_cnt)
    app_cash_44_1d = [x for x in app_1d_gg if re.search(package_id_44, x + "@")]
    app_cash_44_1d_cnt = len(app_cash_44_1d)
    app_cash_44_7d = [x for x in app_7d_gg if re.search(package_id_44, x + "@")]
    app_cash_44_7d_cnt = len(app_cash_44_7d)
    app_cash_1d_div_7d_44_allday = tmp_d(app_cash_44_1d_cnt, app_cash_44_7d_cnt)
    app_cash_1d = [x for x in app_1d if re.search(package_id_loan, x)]
    app_cash_1d_cnt = len(app_cash_1d)
    app_cash = [x for x in app_name_and_id if re.search(package_id_loan, x)]
    app_cash_cnt = len(app_cash)
    app_cash_1d_div_cash_allday = tmp_d(app_cash_1d_cnt, app_cash_cnt)

    app_cash_1d = [x for x in app_1d if re.search(package_id_loan, x)]
    app_cash_1d_cnt = len(app_cash_1d)
    app_1d_cnt = len(app_1d)
    app_cash_1d_rate_allday = tmp_d(app_cash_1d_cnt, app_1d_cnt)

    app_cash_44_3d = [x for x in app_3d_gg if re.search(package_id_44, x + "@")]
    app_cash_44_3d_cnt = len(app_cash_44_3d)
    app_cash_44_15d = [x for x in app_15d_gg if re.search(package_id_44, x + "@")]
    app_cash_44_15d_cnt = len(app_cash_44_15d)
    app_cash_3d_div_15d_44_allday = tmp_d(app_cash_44_3d_cnt, app_cash_44_15d_cnt)

    app_cash_1m_3d = [x for x in app_3d_gg if re.search(package_id_1m, x + "@")]
    app_cash_1m_3d_cnt = len(app_cash_1m_3d)
    app_cash_1m_7d = [x for x in app_7d_gg if re.search(package_id_1m, x + "@")]
    app_cash_1m_7d_cnt = len(app_cash_1m_7d)
    app_cash_3d_div_7d_1m_allday = tmp_d(app_cash_1m_3d_cnt, app_cash_1m_7d_cnt)

    app_cash_3d = [x for x in app_3d if re.search(package_id_loan, x)]
    app_cash_3d_cnt = len(app_cash_3d)
    app_cash_90d = [x for x in app_90d if re.search(package_id_loan, x)]
    app_cash_90d_cnt = len(app_cash_90d)
    app_cash_3d_div_90d_allday = tmp_d(app_cash_3d_cnt, app_cash_90d_cnt)

    """ up """
    app_name_and_id = [x['appName'] + ' ' + x['packageName'] + "@ xw " + str(
        (apply_time_int - cal_strdate_to_int(x['lastUpdateTime'])) / 3600 / 1000 / 24 + random.random() * 0.0001) for x
                       in app_data]
    app_1d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 1]
    app_3d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 3]
    app_7d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 7]
    app_15d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 15]
    app_30d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 30]
    app_60d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 60]
    app_90d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 90]
    app_180d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 180]
    app_360d = [app_name_and_id[up_hours.index(x)] for x in up_hours if x <= 360]

    app_name_and_id_gg = [x['packageName'] for x in app_data]
    app_1d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 1]
    app_3d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 3]
    app_7d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 7]
    app_15d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 15]
    app_30d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 30]
    app_60d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 60]
    app_90d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 90]
    app_180d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 180]
    app_360d_gg = [app_name_and_id_gg[up_hours.index(x)] for x in up_hours if x <= 360]

    app_15d_cnt = len(app_15d)
    app_cash_15d = [x for x in app_15d if re.search(package_id_loan, x)]
    app_cash_15d_cnt = len(app_cash_15d)
    app_cash_15d_rate_upday = tmp_d(app_cash_15d_cnt, app_15d_cnt)

    in_hours_int = [int(x) for x in in_hours]
    app_inday_majority_upday = Counter(in_hours_int).most_common(1)[0][0]
    app_end_time = time.time()
    app_time = app_end_time - app_start_time 
    # 记录日志
    logging.info(f"OrderID {order_id} APP特征集计算模块 execution time: {app_time:.2f}s")
    
    sms_start_time = time.time()
    """ tfidf """
    if isinstance(sms_json, str):
        sms_json = json.loads(sms_json)
    sms_json = [x for x in sms_json if "sms_content" in x.keys()]
    sms_json = [x for x in sms_json if x['sms_content'] and x['send_time'] and x['contactor_name']]
    sms_json = [x for x in sms_json if x['send_time'] >= '2019-10-10 00:00:00']  # 42959038-03-26 03:03:43
    
    sms_json = [{**x, "day": (apply_time_int - cal_strdate_to_int(x["send_time"])) / 3600 / 1000 / 24} for x in sms_json]
    sms_json = [ x for x in sms_json if x["day"]<=180]
    
    sms_json = [x for x in sms_json if
                not re.search(sms_dele_key, unidecode.unidecode(x['sms_content'].lower()))]  # 42959038-03-26 03:03:43
    sms_json = [x for x in sms_json if not re.search(sms_dele_key, unidecode.unidecode(
        x['contactor_name'].lower()))]  # 42959038-03-26 03:03:43

    body = [item['sms_content'].replace('\n', '').lower() + " " + item['contactor_name'].replace('\n', '').lower() for
            item in sms_json]  # 删除换行符
    body = [cal_sms_content(unidecode.unidecode(x.lower())) for x in body]  # 去掉重音符

    send_time = [item['send_time'] for item in sms_json]
    send_time = [cal_strdate_to_int(item['send_time']) for item in sms_json]
    day = [(apply_time_int - x) / 3600 / 1000 / 24 + random.random() * 0.0001 for x in send_time]

    body_1d = [body[day.index(x)] for x in day if x <= 1]
    body_3d = [body[day.index(x)] for x in day if x <= 3]
    body_7d = [body[day.index(x)] for x in day if x <= 7]
    body_15d = [body[day.index(x)] for x in day if x <= 15]
    body_30d = [body[day.index(x)] for x in day if x <= 30]
    body_60d = [body[day.index(x)] for x in day if x <= 60]
    body_90d = [body[day.index(x)] for x in day if x <= 90]
    body_360d = [body[day.index(x)] for x in day if x <= 360]

    body_cnt = len(body)
    body_1d_cnt = len(body_1d)
    body_1d_rate = tmp_d(body_1d_cnt, body_cnt)
    body_3d_cnt = len(body_3d)
    body_3d_rate = tmp_d(body_3d_cnt, body_cnt)
    body_7d_cnt = len(body_7d)
    body_7d_rate = tmp_d(body_7d_cnt, body_cnt)
    body_15d_cnt = len(body_15d)
    body_15d_rate = tmp_d(body_15d_cnt, body_cnt)
    body_30d_cnt = len(body_30d)
    body_30d_rate = tmp_d(body_30d_cnt, body_cnt)
    body_60d_cnt = len(body_60d)
    body_60d_rate = tmp_d(body_60d_cnt, body_cnt)
    body_90d_cnt = len(body_90d)
    body_90d_rate = tmp_d(body_90d_cnt, body_cnt)
    body_360d_cnt = len(body_360d)
    body_360d_rate = tmp_d(body_360d_cnt, body_cnt)

    body_15d_upto = [x for x in body_15d if re.search('approve|up to|approval|interest|upto', x)]
    body_15d_upto_cnt_tfidf = len(body_15d_upto)

    body_legal = [x for x in body if re.search(' legal | law | atty ', x.lower())]
    body_legal_cnt = len(body_legal)
    body_legal_rate = tmp_d(body_legal_cnt, body_cnt)
    body_1d_legal = [x for x in body_1d if re.search(' legal | law | atty ', x.lower())]
    body_1d_legal_cnt = len(body_1d_legal)
    body_1d_legal_rate = tmp_d(body_1d_legal_cnt, body_1d_cnt)
    body_1d_legal_div_legal_tfidf = tmp_d(body_1d_legal_cnt, body_legal_cnt)
    body_1d_pastdue = [x for x in body_1d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_1d_pastdue_cnt_tfidf = len(body_1d_pastdue)
    body_close = [x for x in body if re.search('close', x)]
    body_close_cnt = len(body_close)
    body_30d_close = [x for x in body_30d if re.search('close', x)]
    body_30d_close_cnt = len(body_30d_close)
    body_30d_close_rate = tmp_d(body_30d_close_cnt, body_30d_cnt)
    body_30d_close_div_close_tfidf = tmp_d(body_30d_close_cnt, body_close_cnt)
    body_30d_pastdue = [x for x in body_30d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_30d_pastdue_cnt = len(body_30d_pastdue)
    body_30d_pastdue_rate = tmp_d(body_30d_pastdue_cnt, body_30d_cnt)
    body_pastdue = [x for x in body if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_pastdue_cnt = len(body_pastdue)
    body_30d_pastdue_div_pastdue_tfidf = tmp_d(body_30d_pastdue_cnt, body_pastdue_cnt)

    body_360d_now = [x for x in body_360d if re.search("today|now|tomorrow", x.lower())]
    body_360d_now_cnt_tfidf = len(body_360d_now)

    body_3d_duedate = [x for x in body_3d if re.search(' duedate | dueday | ay due |due date', x.lower())]
    body_3d_duedate_cnt = len(body_3d_duedate)
    body_3d_duedate_rate = tmp_d(body_3d_duedate_cnt, body_3d_cnt)
    body_duedate = [x for x in body if re.search(' duedate | dueday | ay due |due date', x.lower())]
    body_duedate_cnt = len(body_duedate)
    body_3d_duedate_div_duedate_tfidf = tmp_d(body_3d_duedate_cnt, body_duedate_cnt)

    body_7d_reference = [x for x in body_7d if re.search("reference", x.lower())]
    body_7d_reference_cnt = len(body_7d_reference)
    body_7d_reference_rate = tmp_d(body_7d_reference_cnt, body_7d_cnt)
    body_reference = [x for x in body if re.search("reference", x.lower())]
    body_reference_cnt = len(body_reference)
    body_7d_reference_div_reference_tfidf = tmp_d(body_7d_reference_cnt, body_reference_cnt)

    body_1d_apply = [x for x in body_1d if re.search("application|apply", x.lower())]
    body_1d_apply_cnt = len(body_1d_apply)
    body_15d_apply = [x for x in body_15d if re.search("application|apply", x.lower())]
    body_15d_apply_cnt = len(body_15d_apply)
    body_apply_1d_div_15d_tfidf = tmp_d(body_1d_apply_cnt, body_15d_apply_cnt)
    body_apply = [x for x in body if re.search("application|apply", x.lower())]
    body_apply_cnt_tfidf = len(body_apply)

    body_1d_bill = [x for x in body_1d if re.search(" balance | bill | balanse |statement", x.lower())]
    body_1d_bill_cnt = len(body_1d_bill)
    body_7d_bill = [x for x in body_7d if re.search(" balance | bill | balanse |statement", x.lower())]
    body_7d_bill_cnt = len(body_7d_bill)
    body_bill_1d_div_7d_tfidf = tmp_d(body_1d_bill_cnt, body_7d_bill_cnt)

    body_7d_congrat = [x for x in body_7d if re.search('congrat', x)]
    body_7d_congrat_cnt = len(body_7d_congrat)
    body_15d_congrat = [x for x in body_15d if re.search('congrat', x)]
    body_15d_congrat_cnt = len(body_15d_congrat)
    body_congrat_7d_div_15d_tfidf = tmp_d(body_7d_congrat_cnt, body_15d_congrat_cnt)

    body_installment = [x for x in body if re.search('schedule|installment', x)]
    body_installment_cnt_tfidf = len(body_installment)

    body_1d_legal = [x for x in body_1d if re.search(' legal | law | atty ', x.lower())]
    body_1d_legal_cnt = len(body_1d_legal)
    body_3d_legal = [x for x in body_3d if re.search(' legal | law | atty ', x.lower())]
    body_3d_legal_cnt = len(body_3d_legal)
    body_legal_1d_div_3d_tfidf = tmp_d(body_1d_legal_cnt, body_3d_legal_cnt)

    body_7d_legal = [x for x in body_7d if re.search(' legal | law | atty ', x.lower())]
    body_7d_legal_cnt = len(body_7d_legal)
    body_legal_1d_div_7d_tfidf = tmp_d(body_1d_legal_cnt, body_7d_legal_cnt)

    body_15d_now = [x for x in body_15d if re.search("today|now|tomorrow", x.lower())]
    body_15d_now_cnt = len(body_15d_now)
    body_30d_now = [x for x in body_30d if re.search("today|now|tomorrow", x.lower())]
    body_30d_now_cnt = len(body_30d_now)
    body_now_15d_div_30d_tfidf = tmp_d(body_15d_now_cnt, body_30d_now_cnt)

    body_now = [x for x in body if re.search("today|now|tomorrow", x.lower())]
    body_now_cnt_tfidf = len(body_now)

    body_15d_pastdue = [x for x in body_15d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_15d_pastdue_cnt = len(body_15d_pastdue)
    body_90d_pastdue = [x for x in body_90d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_90d_pastdue_cnt = len(body_90d_pastdue)
    body_pastdue_15d_div_90d_tfidf = tmp_d(body_15d_pastdue_cnt, body_90d_pastdue_cnt)

    body_1d_pastdue = [x for x in body_1d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_1d_pastdue_cnt = len(body_1d_pastdue)
    body_3d_pastdue = [x for x in body_3d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_3d_pastdue_cnt = len(body_3d_pastdue)
    body_pastdue_1d_div_3d_tfidf = tmp_d(body_1d_pastdue_cnt, body_3d_pastdue_cnt)
    body_7d_pastdue = [x for x in body_7d if re.search('past due|pastdue|over due|overdue', x.lower())]
    body_7d_pastdue_cnt = len(body_7d_pastdue)
    body_pastdue_1d_div_7d_tfidf = tmp_d(body_1d_pastdue_cnt, body_7d_pastdue_cnt)

    body_30d_upto = [x for x in body_30d if re.search('approve|up to|approval|interest|upto', x)]
    body_30d_upto_cnt = len(body_30d_upto)
    body_60d_upto = [x for x in body_60d if re.search('approve|up to|approval|interest|upto', x)]
    body_60d_upto_cnt = len(body_60d_upto)
    body_upto_30d_div_60d_tfidf = tmp_d(body_30d_upto_cnt, body_60d_upto_cnt)

    body_30d_utang = [x for x in body_30d if re.search("unsettle|utang|debtor|unpaid", x.lower())]
    body_30d_utang_cnt = len(body_30d_utang)
    body_360d_utang = [x for x in body_360d if re.search("unsettle|utang|debtor|unpaid", x.lower())]
    body_360d_utang_cnt = len(body_360d_utang)
    body_utang_30d_div_360d_tfidf = tmp_d(body_30d_utang_cnt, body_360d_utang_cnt)

    body_90d_utang = [x for x in body_90d if re.search("unsettle|utang|debtor|unpaid", x.lower())]
    body_90d_utang_cnt = len(body_90d_utang)
    body_utang_30d_div_90d_tfidf = tmp_d(body_30d_utang_cnt, body_90d_utang_cnt)

    """ sms """
    if isinstance(sms_json, str):
        sms_json = json.loads(sms_json)
    sms_json = [x for x in sms_json if "sms_content" in x.keys()]
    sms_json = [x for x in sms_json if x['sms_content'] and x['send_time'] and x['contactor_name']]
    sms_json = [x for x in sms_json if x['send_time'] >= '2019-10-10 00:00:00']  # 42959038-03-26 03:03:43
    
    sms_json = [{**x, "day": (apply_time_int - cal_strdate_to_int(x["send_time"])) / 3600 / 1000 / 24} for x in sms_json]
    sms_json = [ x for x in sms_json if x["day"]<=180]
    
    sms_json = [x for x in sms_json if not re.search(sms_dele_key, unidecode.unidecode(x['sms_content'].lower()))]
    sms_json = [x for x in sms_json if not re.search(sms_dele_key, unidecode.unidecode(x['contactor_name'].lower()))]

    # 新逻辑
    sms_json = [{**x, 'sms_org': cal_tq_org(x["sms_content"])} for x in sms_json]
    sms_json = [{**x, "sms_org_ok": cal_tq_org_02(x["sms_org"] + x["contactor_name"])} for x in sms_json]
    sms_json = [{**x, "sms_content_ok": cal_sms_content(x["sms_content"])} for x in sms_json]
    sms_json = [{**x, "sms_verif_key": cal_boy_type(x["sms_content_ok"], sms_verif_key)} for x in sms_json]
    sms_json = [{**x, "sms_cash_key": cal_boy_type(x["sms_content_ok"], sms_cash_key)} for x in sms_json]
    sms_json = [{**x, "sms_loan_key": cal_boy_type(x["sms_content_ok"], sms_loan_key)} for x in sms_json]
    sms_json = [{**x, "sms_repayment_key": cal_boy_type(x["sms_content_ok"], sms_repayment_key)} for x in sms_json]
    sms_json = [{**x, "sms_expire_key": cal_boy_type(x["sms_content_ok"], sms_expire_key)} for x in sms_json]
    sms_json = [{**x, "sms_bill_key": cal_boy_type(x["sms_content_ok"], sms_bill_key)} for x in sms_json]
    sms_json = [{**x, "sms_overdue_serious_key": cal_boy_type(x["sms_content_ok"], sms_overdue_serious_key)} for x in
                sms_json]
    sms_json = [
        {**x, "sms_overdue_key": cal_boy_type(x["sms_content_ok"], sms_overdue_key + "|" + sms_overdue_serious_key)} for
        x in sms_json]
    sms_json = [{**x, "sms_topcash_key": cal_boy_type(x["sms_content_ok"], sms_topcash_key)} for x in sms_json]
    sms_json = [{**x, "sms_1m_cash_key": cal_boy_type(x["sms_content_ok"], sms_1m_cash_key)} for x in sms_json]

    sms_json = [{**x, "day": (apply_time_int - cal_strdate_to_int(x["send_time"])) / 3600 / 1000 / 24} for x in
                sms_json]

    body = [x for x in sms_json]
    body_1d = [x for x in sms_json if x["day"] <= 1]
    body_3d = [x for x in sms_json if x["day"] <= 3]
    body_7d = [x for x in sms_json if x["day"] <= 7]
    body_15d = [x for x in sms_json if x["day"] <= 15]
    body_30d = [x for x in sms_json if x["day"] <= 30]
    body_60d = [x for x in sms_json if x["day"] <= 60]
    body_90d = [x for x in sms_json if x["day"] <= 90]
    body_360d = [x for x in sms_json if x["day"] <= 360]

    body_cnt = len(body)
    body_1d_cnt = len(body_1d)
    body_1d_rate = tmp_d(body_1d_cnt, body_cnt)
    body_3d_cnt = len(body_3d)
    body_3d_rate = tmp_d(body_3d_cnt, body_cnt)
    body_7d_cnt = len(body_7d)
    body_7d_rate = tmp_d(body_7d_cnt, body_cnt)
    body_15d_cnt = len(body_15d)
    body_15d_rate = tmp_d(body_15d_cnt, body_cnt)
    body_30d_cnt = len(body_30d)
    body_30d_rate = tmp_d(body_30d_cnt, body_cnt)
    body_60d_cnt = len(body_60d)
    body_60d_rate = tmp_d(body_60d_cnt, body_cnt)
    body_90d_cnt = len(body_90d)
    body_90d_rate = tmp_d(body_90d_cnt, body_cnt)
    body_360d_cnt = len(body_360d)
    body_360d_rate = tmp_d(body_360d_cnt, body_cnt)

    body_overdue_serious = [x['sms_content_ok'] for x in sms_json if x["sms_overdue_serious_key"] == 1]
    body_overdue_serious_cnt = len(body_overdue_serious)
    body_overdue_serious_rate = tmp_d(body_overdue_serious_cnt, body_cnt)
    body_1d_overdue_serious = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_serious_key"] == 1 and x["day"] <= 1]
    body_1d_overdue_serious_cnt = len(body_1d_overdue_serious)
    body_1d_overdue_serious_rate = tmp_d(body_1d_overdue_serious_cnt, body_1d_cnt)
    body_1d_overdue_serious_div_overdue_serious = tmp_d(body_1d_overdue_serious_cnt, body_overdue_serious_cnt)

    body_360d_overdue_serious = [x['sms_content_ok'] for x in sms_json if
                                 x["sms_overdue_serious_key"] == 1 and x["day"] <= 360]
    body_360d_overdue_serious_cnt = len(body_360d_overdue_serious)

    body_3d_bill = [x['sms_content_ok'] for x in sms_json if x["sms_bill_key"] == 1 and x["day"] <= 3]
    body_3d_bill_cnt = len(body_3d_bill)
    body_360d_bill = [x['sms_content_ok'] for x in sms_json if x["sms_bill_key"] == 1 and x["day"] <= 360]
    body_360d_bill_cnt = len(body_360d_bill)
    body_bill_3d_div_360d = tmp_d(body_3d_bill_cnt, body_360d_bill_cnt)

    body_15d_loan_1m_cash = [x['sms_content_ok'] for x in sms_json if
                             x["sms_loan_key"] == 1 and x["sms_1m_cash_key"] == 1 and x["day"] <= 15 and x[
                                 'sms_org_ok'] != "-999"]
    body_15d_loan_1m_cash_cnt = len(body_15d_loan_1m_cash)
    body_90d_loan_1m_cash = [x['sms_content_ok'] for x in sms_json if
                             x["sms_loan_key"] == 1 and x["sms_1m_cash_key"] == 1 and x["day"] <= 90 and x[
                                 'sms_org_ok'] != "-999"]
    body_90d_loan_1m_cash_cnt = len(body_90d_loan_1m_cash)
    body_loan_1m_cash_15d_div_90d = tmp_d(body_15d_loan_1m_cash_cnt, body_90d_loan_1m_cash_cnt)

    body_7d_loan = [x['sms_content_ok'] for x in sms_json if x["sms_loan_key"] == 1 and x["day"] <= 7]
    body_7d_loan_cnt = len(body_7d_loan)
    body_60d_loan = [x['sms_content_ok'] for x in sms_json if x["sms_loan_key"] == 1 and x["day"] <= 60]
    body_60d_loan_cnt = len(body_60d_loan)
    body_loan_7d_div_60d = tmp_d(body_7d_loan_cnt, body_60d_loan_cnt)

    body_7d_loan_topcash = [x['sms_content_ok'] for x in sms_json if
                            x["sms_loan_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 7]
    body_7d_loan_topcash_cnt = len(body_7d_loan_topcash)
    body_15d_loan_topcash = [x['sms_content_ok'] for x in sms_json if
                             x["sms_loan_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 15]
    body_15d_loan_topcash_cnt = len(body_15d_loan_topcash)
    body_loan_topcash_7d_div_15d = tmp_d(body_7d_loan_topcash_cnt, body_15d_loan_topcash_cnt)

    body_1d_overdue_1m_cash = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_1m_cash_key'] == 1
                               and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 1 and
                               x['sms_content_ok'] != "-999"]
    body_1d_overdue_1m_cash_cnt = len(body_1d_overdue_1m_cash)
    body_3d_overdue_1m_cash = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_1m_cash_key'] == 1
                               and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 3 and
                               x['sms_content_ok'] != "-999"]
    body_3d_overdue_1m_cash_cnt = len(body_3d_overdue_1m_cash)
    body_overdue_1m_cash_1d_div_3d = tmp_d(body_1d_overdue_1m_cash_cnt, body_3d_overdue_1m_cash_cnt)

    body_3d_overdue_1m_cash = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_1m_cash_key'] == 1
                               and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 3 and
                               x['sms_content_ok'] != "-999"]
    body_3d_overdue_1m_cash_cnt = len(body_3d_overdue_1m_cash)
    body_15d_overdue_1m_cash = [x['sms_content_ok'] for x in sms_json if
                                x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_1m_cash_key'] == 1
                                and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 15 and
                                x['sms_content_ok'] != "-999"]
    body_15d_overdue_1m_cash_cnt = len(body_15d_overdue_1m_cash)
    body_overdue_1m_cash_3d_div_15d = tmp_d(body_3d_overdue_1m_cash_cnt, body_15d_overdue_1m_cash_cnt)

    body_7d_overdue = [x['sms_content_ok'] for x in sms_json if x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0
                       and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 7 and x[
                           'sms_org_ok'] != "-999"]
    body_7d_overdue_cnt = len(body_7d_overdue)
    body_360d_overdue = [x['sms_content_ok'] for x in sms_json if x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0
                         and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 360 and x[
                             'sms_org_ok'] != "-999"]
    body_360d_overdue_cnt = len(body_360d_overdue)
    body_overdue_7d_div_360d = tmp_d(body_7d_overdue_cnt, body_360d_overdue_cnt)
    body_overdue = [x['sms_content_ok'] for x in sms_json if x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0
                    and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0]
    body_overdue_cnt = len(body_overdue)

    body_1d_overdue_serious = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_serious_key"] == 1 and x["day"] <= 1]
    body_1d_overdue_serious_cnt = len(body_1d_overdue_serious)
    body_3d_overdue_serious = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_serious_key"] == 1 and x["day"] <= 3]
    body_3d_overdue_serious_cnt = len(body_3d_overdue_serious)
    body_overdue_serious_1d_div_3d = tmp_d(body_1d_overdue_serious_cnt, body_3d_overdue_serious_cnt)
    body_7d_overdue_serious = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_serious_key"] == 1 and x["day"] <= 7]
    body_7d_overdue_serious_cnt = len(body_7d_overdue_serious)
    body_overdue_serious_1d_div_7d = tmp_d(body_1d_overdue_serious_cnt, body_7d_overdue_serious_cnt)

    body_30d_overdue_serious_topcash = [x['sms_content_ok'] for x in sms_json if
                                        x["sms_overdue_serious_key"] == 1 and x["sms_topcash_key"] == 1 and x[
                                            "day"] <= 30]
    body_30d_overdue_serious_topcash_cnt = len(body_30d_overdue_serious_topcash)
    body_360d_overdue_serious_topcash = [x['sms_content_ok'] for x in sms_json if
                                         x["sms_overdue_serious_key"] == 1 and x["sms_topcash_key"] == 1 and x[
                                             "day"] <= 360]
    body_360d_overdue_serious_topcash_cnt = len(body_360d_overdue_serious_topcash)
    body_overdue_serious_topcash_30d_div_360d = tmp_d(body_30d_overdue_serious_topcash_cnt,
                                                      body_360d_overdue_serious_topcash_cnt)

    body_3d_overdue_topcash = [x['sms_content_ok'] for x in sms_json if
                               x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_topcash_key'] == 1
                               and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x["day"] <= 3 and
                               x['sms_content_ok'] != "-999"]
    body_3d_overdue_topcash_cnt = len(body_3d_overdue_topcash)
    body_360d_overdue_topcash = [x['sms_content_ok'] for x in sms_json if
                                 x["sms_overdue_key"] == 1 and x['sms_loan_key'] == 0 and x['sms_topcash_key'] == 1
                                 and x['sms_repayment_key'] == 0 and x['sms_expire_key'] == 0 and x[
                                     "day"] <= 360 and x['sms_content_ok'] != "-999"]
    body_360d_overdue_topcash_cnt = len(body_360d_overdue_topcash)
    body_overdue_topcash_3d_div_360d = tmp_d(body_3d_overdue_topcash_cnt, body_360d_overdue_topcash_cnt)

    body_1d_settle_topcash = [x['sms_content_ok'] for x in sms_json if
                              x["sms_repayment_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 1]
    body_1d_settle_topcash_cnt = len(body_1d_settle_topcash)
    body_30d_settle_topcash = [x['sms_content_ok'] for x in sms_json if
                               x["sms_repayment_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 30]
    body_30d_settle_topcash_cnt = len(body_30d_settle_topcash)
    body_settle_topcash_1d_div_30d = tmp_d(body_1d_settle_topcash_cnt, body_30d_settle_topcash_cnt)

    """ org """
    if isinstance(sms_json, str):
        sms_json = json.loads(sms_json)
    sms_json = [x for x in sms_json if "sms_content" in x.keys()]
    sms_json = [x for x in sms_json if x['sms_content'] and x['send_time'] and x['contactor_name']]
    sms_json = [x for x in sms_json if x['send_time'] >= '2019-10-10 00:00:00']  # 42959038-03-26 03:03:43
    
    sms_json = [{**x, "day": (apply_time_int - cal_strdate_to_int(x["send_time"])) / 3600 / 1000 / 24} for x in sms_json]
    sms_json = [ x for x in sms_json if x["day"]<=180]
    
    sms_json = [x for x in sms_json if not re.search(sms_dele_key, unidecode.unidecode(x['sms_content'].lower()))]
    sms_json = [x for x in sms_json if not re.search(sms_dele_key, unidecode.unidecode(x['contactor_name'].lower()))]

    sms_json = [{**x, 'sms_org': cal_tq_org(x["sms_content"])} for x in sms_json]
    sms_json = [{**x, "sms_org_ok": cal_tq_org_02(x["sms_org"] + x["contactor_name"])} for x in sms_json]
    sms_json = [{**x, "sms_content_ok": cal_sms_content(x["sms_content"])} for x in sms_json]
    sms_json = [{**x, "sms_verif_key": cal_boy_type(x["sms_content_ok"], sms_verif_key)} for x in sms_json]
    sms_json = [{**x, "sms_cash_key": cal_boy_type(x["sms_content_ok"], sms_cash_key)} for x in sms_json]
    sms_json = [{**x, "sms_loan_key": cal_boy_type(x["sms_content_ok"], sms_loan_key)} for x in sms_json]
    sms_json = [{**x, "sms_repayment_key": cal_boy_type(x["sms_content_ok"], sms_repayment_key)} for x in sms_json]
    sms_json = [{**x, "sms_expire_key": cal_boy_type(x["sms_content_ok"], sms_expire_key)} for x in sms_json]
    sms_json = [{**x, "sms_bill_key": cal_boy_type(x["sms_content_ok"], sms_bill_key)} for x in sms_json]
    sms_json = [{**x, "sms_overdue_serious_key": cal_boy_type(x["sms_content_ok"], sms_overdue_serious_key)} for x in
                sms_json]
    sms_json = [
        {**x, "sms_overdue_key": cal_boy_type(x["sms_content_ok"], sms_overdue_key + "|" + sms_overdue_serious_key)} for
        x in sms_json]
    sms_json = [{**x, "sms_topcash_key": cal_boy_type(x["sms_org_ok"], sms_topcash_key)} for x in sms_json]
    sms_json = [{**x, "sms_1m_cash_key": cal_boy_type(x["sms_org_ok"], sms_1m_cash_key)} for x in sms_json]

    sms_json = [{**x, "day": (apply_time_int - cal_strdate_to_int(x["send_time"])) / 3600 / 1000 / 24} for x in
                sms_json]

    body = [x for x in sms_json]
    body_1d = [x for x in sms_json if x["day"] <= 1]
    body_3d = [x for x in sms_json if x["day"] <= 3]
    body_7d = [x for x in sms_json if x["day"] <= 7]
    body_15d = [x for x in sms_json if x["day"] <= 15]
    body_30d = [x for x in sms_json if x["day"] <= 30]
    body_60d = [x for x in sms_json if x["day"] <= 60]
    body_90d = [x for x in sms_json if x["day"] <= 90]
    body_360d = [x for x in sms_json if x["day"] <= 360]

    body_cnt = len(body)
    body_1d_cnt = len(body_1d)
    body_1d_rate = tmp_d(body_1d_cnt, body_cnt)
    body_3d_cnt = len(body_3d)
    body_3d_rate = tmp_d(body_3d_cnt, body_cnt)
    body_7d_cnt = len(body_7d)
    body_7d_rate = tmp_d(body_7d_cnt, body_cnt)
    body_15d_cnt = len(body_15d)
    body_15d_rate = tmp_d(body_15d_cnt, body_cnt)
    body_30d_cnt = len(body_30d)
    body_30d_rate = tmp_d(body_30d_cnt, body_cnt)
    body_60d_cnt = len(body_60d)
    body_60d_rate = tmp_d(body_60d_cnt, body_cnt)
    body_90d_cnt = len(body_90d)
    body_90d_rate = tmp_d(body_90d_cnt, body_cnt)
    body_360d_cnt = len(body_360d)
    body_360d_rate = tmp_d(body_360d_cnt, body_cnt)

    body_1d_verif = [x['sms_org_ok'] for x in sms_json if
                     x["sms_verif_key"] == 1 and x['sms_org_ok'] != "-999" and x["day"] <= 1]
    body_1d_verif = set(body_1d_verif)
    body_1d_verif_cnt_org = len(body_1d_verif)
    body_1d_verif_cnt = len(body_1d_verif)
    body_1d_verif_rate_org = tmp_d(body_1d_verif_cnt, body_1d_cnt)

    body_360d_cnt_org = len(body_360d)

    body_3d_verif = [x['sms_org_ok'] for x in sms_json if
                     x["sms_verif_key"] == 1 and x["day"] <= 3 and x['sms_org_ok'] != "-999"]
    body_3d_verif = set(body_3d_verif)
    body_3d_verif_cnt = len(body_3d_verif)
    body_3d_verif_rate_org = tmp_d(body_3d_verif_cnt, body_3d_cnt)

    body_60d_verif = [x['sms_org_ok'] for x in sms_json if
                      x["sms_verif_key"] == 1 and x["day"] <= 60 and x['sms_org_ok'] != "-999"]
    body_60d_verif = set(body_60d_verif)
    body_60d_verif_cnt = len(body_60d_verif)
    body_60d_verif_rate_org = tmp_d(body_60d_verif_cnt, body_60d_cnt)

    body_7d_settle = [x['sms_org_ok'] for x in sms_json if
                      x["sms_repayment_key"] == 1 and x["day"] <= 7 and x['sms_org_ok'] != "-999"]
    body_7d_settle = set(body_7d_settle)
    body_7d_settle_cnt = len(body_7d_settle)
    body_7d_settle_rate = tmp_d(body_7d_settle_cnt, body_7d_cnt)
    body_settle = [x['sms_org_ok'] for x in sms_json if x["sms_repayment_key"] == 1 and x['sms_org_ok'] != "-999"]
    body_settle = set(body_settle)
    body_settle_cnt = len(body_settle)
    body_7d_settle_div_settle_org = tmp_d(body_7d_settle_cnt, body_settle_cnt)

    body_7d_verif = [x['sms_org_ok'] for x in sms_json if
                     x["sms_verif_key"] == 1 and x["day"] <= 7 and x['sms_org_ok'] != "-999"]
    body_7d_verif = set(body_7d_verif)
    body_7d_verif_cnt = len(body_7d_verif)
    body_7d_verif_rate_org = tmp_d(body_7d_verif_cnt, body_7d_cnt)

    body_cnt_org = len(body)

    body_3d_expire_topcash = [x['sms_org_ok'] for x in sms_json if
                              x["sms_expire_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 3 and x[
                                  'sms_org_ok'] != "-999"]
    body_3d_expire_topcash = set(body_3d_expire_topcash)
    body_3d_expire_topcash_cnt = len(body_3d_expire_topcash)
    body_15d_expire_topcash = [x['sms_org_ok'] for x in sms_json if
                               x["sms_expire_key"] == 1 and x["sms_topcash_key"] == 1 and x["day"] <= 15 and x[
                                   'sms_org_ok'] != "-999"]
    body_15d_expire_topcash = set(body_15d_expire_topcash)
    body_15d_expire_topcash_cnt = len(body_15d_expire_topcash)
    body_expire_topcash_3d_div_15d_org = tmp_d(body_3d_expire_topcash_cnt, body_15d_expire_topcash_cnt)

    sms_end_time = time.time()
    sms_time = sms_end_time - sms_start_time
    # 记录日志
    logging.info(f"OrderID {order_id} 短信特征集计算模块 execution time: {sms_time:.2f}s")

    beh_start_time = time.time()

    """ beh """

    day_1 = subtract_days_from_date_str(ApplyDate, 1)
    day_3 = subtract_days_from_date_str(ApplyDate, 3)
    day_5 = subtract_days_from_date_str(ApplyDate, 5)
    day_7 = subtract_days_from_date_str(ApplyDate, 7)
    day_15 = subtract_days_from_date_str(ApplyDate, 15)
    day_30 = subtract_days_from_date_str(ApplyDate, 30)
    day_60 = subtract_days_from_date_str(ApplyDate, 60)
    day_90 = subtract_days_from_date_str(ApplyDate, 90)
    day_360 = subtract_days_from_date_str(ApplyDate, 360)

    """ 使用参数 完成 df_apply_all """

    df_phone = df_apply_all[(df_apply_all['id_number'] == id_number)
                            & (df_apply_all['created_at'] <= created_at)
                            & (df_apply_all['order_id'] != order_id)
                            & (df_apply_all['loan_time'] >= "2000")
                            ]

    df_phone = df_phone.sort_values(by=['created_at'])
    df_phone[['created_at', "ReDate", 'loan_time', 'fact_time']]
    tmp = df_phone[(df_phone['fact_time'] > '2000') & (df_phone['fact_time'] <= apply_time_tmp)]

    tmp_product = tmp[tmp['ProjectId'] == ProjectId]
    if tmp_product.shape[0]:
        last_self_product_overdue_days = list(tmp_product['overdue_days_xw'])[-1]
    else:
        last_self_product_overdue_days = None

    if tmp.shape[0]:
        last_overdue_days = list(tmp['overdue_days_xw'])[-1]

    else:
        # print(order_id, "无结清天数")
        last_overdue_days = -999

    tmp_15day = tmp[tmp['created_at'] >= day_15]
    if tmp_15day.shape[0]:
        overdue_15day_max = max(tmp_15day['overdue_days_xw'])
        overdue_15day_min = min(tmp_15day['overdue_days_xw'])
        overdue_15day_mean = sum(tmp_15day['overdue_days_xw']) / tmp_15day.shape[0]

    else:
        overdue_15day_max = None
        overdue_15day_min = None
        overdue_15day_mean = None

    tmp_30day = tmp[tmp['created_at'] >= day_30]
    if tmp_30day.shape[0]:
        overdue_30day_max = max(tmp_30day['overdue_days_xw'])
        overdue_30day_min = min(tmp_30day['overdue_days_xw'])
        overdue_30day_mean = sum(tmp_30day['overdue_days_xw']) / tmp_30day.shape[0]

    else:
        overdue_30day_max = None
        overdue_30day_min = None
        overdue_30day_mean = None

    # 20240729 变量类型转换
    tmp['plan_repayment_amount'] = tmp['plan_repayment_amount'].astype('int64')
    overdue_days_amount = tmp.groupby(['overdue_days_xw'])['plan_repayment_amount'].sum()
    overdue_days_amount_min = overdue_days_amount.min()
    if overdue_days_amount_min is np.nan:
        overdue_days_amount_min = -999
    else:
        overdue_days_amount_min = int(overdue_days_amount_min)

    # overdue_days_amount_min = int(overdue_days_amount_min)
    # print(overdue_days_amount_min)

    """# 还款时间和申请时间  要包含当前申请件   测试 ：      loan_record_id =   ********************************** **********************"""
    df_phone = df_apply_all[(df_apply_all['id_number'] == id_number)
                            & (df_apply_all['created_at'] <= created_at)
                            & (df_apply_all['loan_time'] >= "2000")
                            ]  # 包含当前申请

    df_phone = df_phone.sort_values(by=['created_at'])

    tmp = df_phone[(df_phone['fact_time'] <= created_at) | (df_phone['order_id'] == order_id)]

    # 多包分组 排序计算
    hours_list = []
    for app_id in set(list(tmp['ProjectId'])):
        df_app_id = tmp[tmp['ProjectId'] == app_id]

        apply_time_list = list(df_app_id['created_at'])
        apply_time_list = [str(x)[:19] for x in apply_time_list]
        apply_time_list = apply_time_list[1:]
        apply_time_stamp_list = [cal_timestamp(cal_strdate_to_int(x)  ) for x in apply_time_list]

        refund_time_list = list(df_app_id['fact_time'])
        refund_time_list = [str(x)[:19] for x in refund_time_list]
        refund_time_list = refund_time_list[:-1]
        refund_time_stamp_list = [cal_timestamp(cal_strdate_to_int(x)  ) for x in refund_time_list]

        hours = list(map(lambda x: cal_hours(x[0], x[1]), zip(apply_time_stamp_list, refund_time_stamp_list)))
        hours_list.extend(hours)

    if hours_list:
        max_apply_fact_hours = max(hours_list)
        min_apply_fact_hours = min(hours_list)
        mean_apply_fact_hours = sum(hours_list) / len(hours_list)
    else:
        max_apply_fact_hours = None
        min_apply_fact_hours = None
        mean_apply_fact_hours = None

    """# 申请时间和申请时间  要包含当前申请件   测试 ：      loan_record_id =   ********************************** **********************"""
    df_phone = df_apply_all[(df_apply_all['id_number'] == id_number)
                            & (df_apply_all['created_at'] <= created_at)
                            & (df_apply_all['loan_time'] >= "2000")]  # 包含当前申请
    df_phone = df_phone.sort_values(by=['created_at'])

    tmp = df_phone

    apply_time_list_0 = list(tmp['created_at'])
    apply_time_list_0 = [str(x)[:19] for x in apply_time_list_0]
    apply_time_list_0 = apply_time_list_0[0:-1]
    apply_time_stamp_list_0 = [cal_timestamp(cal_strdate_to_int(x) ) for x in apply_time_list_0]

    apply_time_list_1 = list(tmp['created_at'])
    apply_time_list_1 = [str(x)[:19] for x in apply_time_list_1]
    apply_time_list_1 = apply_time_list_1[1:]
    apply_time_stamp_list_1 = [cal_timestamp(cal_strdate_to_int(x)  ) for x in apply_time_list_1]

    apply_apply_hours = list(
        map(lambda x: cal_hours(x[0], x[1]), zip(apply_time_stamp_list_1, apply_time_stamp_list_0)))
    if apply_apply_hours:
        max_apply_apply_hours = max(apply_apply_hours)
        min_apply_apply_hours = min(apply_apply_hours)
        mean_apply_apply_hours = sum(apply_apply_hours) / len(apply_apply_hours)
        last_apply_apply_hours = apply_apply_hours[-1]
    else:
        max_apply_apply_hours = None
        min_apply_apply_hours = None
        mean_apply_apply_hours = None
        last_apply_apply_hours = None
    beh_end_time = time.time()
    beh_time = beh_end_time - beh_start_time
    # 记录日志
    logging.info(f"OrderID {order_id} beh特征集计算模块 execution time: {beh_time:.2f}s")

    model_variables = {
        "app_3d_cnt_inday": app_3d_cnt_inday,
        "app_cash_1d_div_cash_allday": app_cash_1d_div_cash_allday,
        "min_apply_fact_hours": min_apply_fact_hours,
        "mean_apply_fact_hours": mean_apply_fact_hours,
        "last_apply_apply_hours": last_apply_apply_hours,
        "app_cash_1d_rate_inday": app_cash_1d_rate_inday,
        "last_overdue_days": last_overdue_days,
        "body_3d_verif_rate_org": body_3d_verif_rate_org,
        "degree": degree,
        "body_30d_pastdue_div_pastdue_tfidf": body_30d_pastdue_div_pastdue_tfidf,
        "body_7d_verif_rate_org": body_7d_verif_rate_org,
        "body_1d_pastdue_cnt_tfidf": body_1d_pastdue_cnt_tfidf,
        "body_pastdue_15d_div_90d_tfidf": body_pastdue_15d_div_90d_tfidf,
        "app_cash_15d_rate_upday": app_cash_15d_rate_upday,
        "body_overdue_1m_cash_3d_div_15d": body_overdue_1m_cash_3d_div_15d,
        "body_1d_legal_div_legal_tfidf": body_1d_legal_div_legal_tfidf,
        "overdue_30day_mean": overdue_30day_mean,
        "body_overdue_serious_1d_div_3d": body_overdue_serious_1d_div_3d,
        "body_installment_cnt_tfidf": body_installment_cnt_tfidf,
        "body_360d_cnt_org": body_360d_cnt_org,
        "body_3d_duedate_div_duedate_tfidf": body_3d_duedate_div_duedate_tfidf,
        "body_1d_overdue_serious_div_overdue_serious": body_1d_overdue_serious_div_overdue_serious,
        "body_now_15d_div_30d_tfidf": body_now_15d_div_30d_tfidf,
        "body_expire_topcash_3d_div_15d_org": body_expire_topcash_3d_div_15d_org,
        "app_cash_3d_div_180d_inday": app_cash_3d_div_180d_inday,
        "age": age,
        "app_cash_15d_div_360d_46_inday": app_cash_15d_div_360d_46_inday,
        "body_overdue_1m_cash_1d_div_3d": body_overdue_1m_cash_1d_div_3d,
        "body_overdue_serious_1d_div_7d": body_overdue_serious_1d_div_7d,
        "app_cash_7d_div_180d_48_inday": app_cash_7d_div_180d_48_inday,
        "app_cash_1d_rate_allday": app_cash_1d_rate_allday,
        "app_3d_cnt_allday": app_3d_cnt_allday,
        "body_60d_verif_rate_org": body_60d_verif_rate_org,
        "body_360d_overdue_serious_cnt": body_360d_overdue_serious_cnt,
        "body_utang_30d_div_90d_tfidf": body_utang_30d_div_90d_tfidf,
        "body_cnt_org": body_cnt_org,
        "body_360d_now_cnt_tfidf": body_360d_now_cnt_tfidf,
        "app_3d_div_90d_inday": app_3d_div_90d_inday,
        "body_overdue_cnt": body_overdue_cnt,
        "body_apply_cnt_tfidf": body_apply_cnt_tfidf,
        "body_overdue_serious_topcash_30d_div_360d": body_overdue_serious_topcash_30d_div_360d,
        "body_pastdue_1d_div_3d_tfidf": body_pastdue_1d_div_3d_tfidf,
        "body_15d_upto_cnt_tfidf": body_15d_upto_cnt_tfidf,
        "body_apply_1d_div_15d_tfidf": body_apply_1d_div_15d_tfidf,
        "overdue_days_amount_min": overdue_days_amount_min,
        "body_settle_topcash_1d_div_30d": body_settle_topcash_1d_div_30d,
        "app_inday_majority_upday": app_inday_majority_upday,
        "body_utang_30d_div_360d_tfidf": body_utang_30d_div_360d_tfidf,
        "body_7d_reference_div_reference_tfidf": body_7d_reference_div_reference_tfidf,
        "body_bill_3d_div_360d": body_bill_3d_div_360d,
        "body_loan_topcash_7d_div_15d": body_loan_topcash_7d_div_15d,
        "body_1d_verif_rate_org": body_1d_verif_rate_org,
        "body_legal_1d_div_3d_tfidf": body_legal_1d_div_3d_tfidf,
        "app_cash_3d_div_30d_inday": app_cash_3d_div_30d_inday,
        "body_1d_verif_cnt_org": body_1d_verif_cnt_org,
        "app_cash_3d_div_7d_1m_allday": app_cash_3d_div_7d_1m_allday,
        "body_7d_settle_div_settle_org": body_7d_settle_div_settle_org,
        "body_now_cnt_tfidf": body_now_cnt_tfidf,
        "body_overdue_topcash_3d_div_360d": body_overdue_topcash_3d_div_360d,
        "app_cash_3d_div_90d_allday": app_cash_3d_div_90d_allday,
        "body_loan_7d_div_60d": body_loan_7d_div_60d,
        "body_pastdue_1d_div_7d_tfidf": body_pastdue_1d_div_7d_tfidf,
        "overdue_15day_max": overdue_15day_max,
        "body_30d_close_div_close_tfidf": body_30d_close_div_close_tfidf,
        "body_overdue_7d_div_360d": body_overdue_7d_div_360d,
        "body_upto_30d_div_60d_tfidf": body_upto_30d_div_60d_tfidf,
        "body_bill_1d_div_7d_tfidf": body_bill_1d_div_7d_tfidf,
        "body_legal_1d_div_7d_tfidf": body_legal_1d_div_7d_tfidf,
        "body_congrat_7d_div_15d_tfidf": body_congrat_7d_div_15d_tfidf,
        "app_cash_1d_div_7d_44_allday": app_cash_1d_div_7d_44_allday,
        "app_3d_div_30d_allday": app_3d_div_30d_allday,
        "body_loan_1m_cash_15d_div_90d": body_loan_1m_cash_15d_div_90d,
        "app_cash_3d_div_15d_44_allday": app_cash_3d_div_15d_44_allday,

    }
    model_variables = {k: -999 if v is None else v for k, v in model_variables.items()}
    df_tmp = pd.DataFrame(model_variables,index=[1])
    df_tmp.fillna(-999, inplace=True)
    var = [
        'app_3d_cnt_inday',
        'app_cash_1d_div_cash_allday',
        'min_apply_fact_hours',
        'mean_apply_fact_hours',
        'last_apply_apply_hours',
        'app_cash_1d_rate_inday',
        'last_overdue_days',
        'body_3d_verif_rate_org',
        'degree',
        'body_30d_pastdue_div_pastdue_tfidf',
        'body_7d_verif_rate_org',
        'body_1d_pastdue_cnt_tfidf',
        'body_pastdue_15d_div_90d_tfidf',
        'app_cash_15d_rate_upday',
        'body_overdue_1m_cash_3d_div_15d',
        'body_1d_legal_div_legal_tfidf',
        'overdue_30day_mean',
        'body_overdue_serious_1d_div_3d',
        'body_installment_cnt_tfidf',
        'body_360d_cnt_org',
        'body_3d_duedate_div_duedate_tfidf',
        'body_1d_overdue_serious_div_overdue_serious',
        'body_now_15d_div_30d_tfidf',
        'body_expire_topcash_3d_div_15d_org',
        'app_cash_3d_div_180d_inday',
        'age',
        'app_cash_15d_div_360d_46_inday',
        'body_overdue_1m_cash_1d_div_3d',
        'body_overdue_serious_1d_div_7d',
        'app_cash_7d_div_180d_48_inday',
        'app_cash_1d_rate_allday',
        'app_3d_cnt_allday',
        'body_60d_verif_rate_org',
        'body_360d_overdue_serious_cnt',
        'body_utang_30d_div_90d_tfidf',
        'body_cnt_org',
        'body_360d_now_cnt_tfidf',
        'app_3d_div_90d_inday',
        'body_overdue_cnt',
        'body_apply_cnt_tfidf',
        'body_overdue_serious_topcash_30d_div_360d',
        'body_pastdue_1d_div_3d_tfidf',
        'body_15d_upto_cnt_tfidf',
        'body_apply_1d_div_15d_tfidf',
        'overdue_days_amount_min',
        'body_settle_topcash_1d_div_30d',
        'app_inday_majority_upday',
        'body_utang_30d_div_360d_tfidf',
        'body_7d_reference_div_reference_tfidf',
        'body_bill_3d_div_360d',
        'body_loan_topcash_7d_div_15d',
        'body_1d_verif_rate_org',
        'body_legal_1d_div_3d_tfidf',
        'app_cash_3d_div_30d_inday',
        'body_1d_verif_cnt_org',
        'app_cash_3d_div_7d_1m_allday',
        'body_7d_settle_div_settle_org',
        'body_now_cnt_tfidf',
        'body_overdue_topcash_3d_div_360d',
        'app_cash_3d_div_90d_allday',
        'body_loan_7d_div_60d',
        'body_pastdue_1d_div_7d_tfidf',
        'overdue_15day_max',
        'body_30d_close_div_close_tfidf',
        'body_overdue_7d_div_360d',
        'body_upto_30d_div_60d_tfidf',
        'body_bill_1d_div_7d_tfidf',
        'body_legal_1d_div_7d_tfidf',
        'body_congrat_7d_div_15d_tfidf',
        'app_cash_1d_div_7d_44_allday',
        'app_3d_div_30d_allday',
        'body_loan_1m_cash_15d_div_90d',
        'app_cash_3d_div_15d_44_allday',
    ]




    # file_path_name = './model/old_v1_20240714.pkl'
    # v1_old_pkl = load_pickle(file_path_name)
    
    file_path_name = 'old_v1_20240714.pkl'
    v1_old_pkl = get_pickle(file_path_name, request)
    
    
    preds = v1_old_pkl.predict(df_tmp[var])




    score_off = p2score(preds)

    # score_oot = 544

    # diff = abs(score_off-score_oot)

    # if diff>=0.0001:
    #     print("有误",order_id,score_oot,score_off,diff)
    # else:
    #     print("无误",order_id,score_oot,score_off)
        
    result = {
        'free_features':model_variables,
        'order_id':order_id,
        'XWOldScoreV1':score_off,
    }
    end_time = time.time()
    print('app消耗时间：', app_end_time - app_start_time)
    print('sms消耗时间：', sms_end_time - sms_start_time)
    print('beh消耗时间：', beh_end_time - beh_start_time)
    print('整体打出评分时间:', end_time - start_time)
    print('短信条数：', body_cnt)
    return result


def send_post_request(url, params):
    # 发送POST请求
    response = requests.post(url, data=params)
    
    # 检查请求是否成功
    if response.status_code == 200:
        # 解析JSON响应
        result = response.json()
        ProjectId = result.get("ProjectId")
        order_id = result.get("ApplyNO")
        apply_time = result.get("ApplyDate")
        app_data = result.get("AppList")
        sms_json = result.get("SmsList")
        birthday = result.get("Birthday")
        degree = result.get("Education")
        id_number = result.get("Phone")

        # 增加婚姻信息字段
        Maritalstatus = result.get("Maritalstatus")

        # 还款表
        id_number_json = result.get("id_number_json")
        
        params = {
            'ProjectId': ProjectId,
            'order_id': order_id,
            'apply_time': apply_time,
            'birthday': birthday,
            'degree': degree,
            'Maritalstatus': Maritalstatus,
            'app_data': app_data,
            'sms_json': sms_json,
            'id_number': id_number,
            'id_number_json': id_number_json,
        }
        return params
    else:
        print(f"Request failed with status code {response.status_code}")
        return None

# 测试样例
if __name__ == '__main__':
    url = "http://polo.philippines1.top/test/getRiskApiTestData"  # 替换为实际API的URL
    
    # val_df = pd.read_excel('./old_v1_oot_模型分_20240817.xlsx')
    # val_df['order_ids_1'] = val_df['order_ids'].str.replace('s','')

    # for ApplyNO in val_df.head(10)['order_ids_1'].tolist():
    for ApplyNO in ['172482962364492023']:
        
            params = {"ApplyNO": ApplyNO, "ApiType": "XWOldScoreV1"} 
            # 获取技术侧准备的数据集 
            test_params = send_post_request(url, params)
            print(test_params)
            # 获取线上计算的新客模型评分
            result = get_old_v1_score(test_params, request=None)
            print(result)
            # gfNewScoreV1, df_tmp, order_id = cal_api_new_v1(test_params)
            # val_df_1 = val_df[val_df['order_ids'].str.contains(order_id)]
            # score_val = val_df_1['score'].tolist()[0]
            # if np.abs(gfNewScoreV1 - score_val) <= 0.1:
            #     print('订单ID', order_id, '无误', '线上评分：', gfNewScoreV1, '线下评分: ', score_val)
            # else:
            #     print('订单ID', order_id, '有偏差: ', np.abs(gfNewScoreV1 - score_val), '线上评分：', gfNewScoreV1, '线下评分: ', score_val)
            #     for var in df_tmp.columns.tolist():
            #         online_var_value = df_tmp[var].tolist()[0]
            #         offline_var_value = val_df_1[var].tolist()[0]
            #         if np.abs(online_var_value - offline_var_value) > 0.1:
            #             print('入模变量：', var, '线上计算值：', online_var_value, '线下计算值：', offline_var_value)

            # print("*"*100)
        # except Exception as e:
        #     print(f"订单ID {ApplyNO} 发生异常错误发生: {e}")
        #     print("*"*100)
    

















